﻿using System;
using System.Collections.Generic;
using System.Configuration;
using Citi.PTSConsolidation.Domain;
using Citi.PTSConsolidation.Domain.Utils;
using Citi.PTSConsolidation.SchedulerUI.Bases;
using Citi.RoutineBase;

namespace Citi.PTSConsolidation.SchedulerUI
{
    internal class ApplicationExtraction
    {
        public IEnumerable<RoutineParameter> Parameters { get { return null; } }
        private static string PtsConnectionString { get { return ConfigurationManager.AppSettings["PtsConnectionString"]; } }
        private static string EntrepotConnectionString { get { return ConfigurationManager.AppSettings["EntrepotConnectionString"]; } }

        public static void ExtractData(int year, ref ICurrentAction currentAction, IDictionary<string, object> parameters, DateTime scheduledDate)
        {
            currentAction.Description = string.Format("Starting Application Extraction {0}", year);

            var ptsTableName = "ApplicationBookOfWork";

            ArchiveOldData(year, currentAction, ptsTableName);
            DropPreviousData(year, currentAction, scheduledDate, ptsTableName);

            currentAction.StartLog("Extracting");
            ExtractDataFromEntrepot(year, currentAction, parameters);
            currentAction.StopLog();

            DeleteNonBr(year, currentAction, ptsTableName);
            ValidateFullYear(year, currentAction, ptsTableName);

            currentAction.Description = string.Format("Application Extraction {0} Finished", year);
        }

        private static void ValidateFullYear(int year, ICurrentAction currentAction, string ptsTableName)
        {
            try
            {
                if (year <= DateTime.Today.Year)
                {
                    currentAction.Description = "Validating FullYear";
                    var queryValidateFullYear = GenericBookOfWork.GetQueryValidateFullYear(ptsTableName, year, DateTime.Today);
                    currentAction.Description = queryValidateFullYear;
                    var fullYear = SqlHelper.ExecuteReader(queryValidateFullYear, PtsConnectionString);

                    if (fullYear.Rows[0][0].ToString() == "1")
                        currentAction.Description = "FullYear validated";
                    else
                        throw new InvalidOperationException("FullYear Sum is invalid. This routine must run again");
                }
            }
            catch (InvalidOperationException e)
            {
                throw e;
            }
            catch
            {
                currentAction.Description = "Error on validating";
            }
        }

        private static void DeleteNonBr(int year, ICurrentAction currentAction, string ptsTableName)
        {
            currentAction.Description = "Deleting Data Non-BR";
            var queryDeleteNonBr = GenericBookOfWork.GetQueryDeleteNonBr(ptsTableName, year);
            currentAction.Description = queryDeleteNonBr;
            SqlHelper.ExecuteReader(queryDeleteNonBr, PtsConnectionString);
        }

        private static void DropPreviousData(int year, ICurrentAction currentAction, DateTime scheduledDate, string ptsTableName)
        {
            currentAction.Description = "Dropping previous data";
            var query = GenericBookOfWork.GetQueryDuplicateData(ptsTableName, year, scheduledDate);
            currentAction.Description = query;
            SqlHelper.ExecuteReader(query, PtsConnectionString);
        }

        private static void ArchiveOldData(int year, ICurrentAction currentAction, string ptsTableName)
        {
            var daysToArchive = 5;
            currentAction.Description = string.Format("Archiving old data. Last {0} days will be archived.", daysToArchive);
            var query = GenericBookOfWork.GetQueryHistoryBOW(ptsTableName, year, daysToArchive);
            currentAction.Description = query;
            SqlHelper.ExecuteReader(query, PtsConnectionString);
        }

        private static void ExtractDataFromEntrepot(int year, ICurrentAction currentAction, IDictionary<string, object> parameters)
        {
            currentAction.Description = string.Format("Application Extraction {0}: Copy has started", year);

            var robotUsername = parameters["RobotUsername"].ToString();
            var robotPassword = parameters["RobotPassword"].ToString();
            var projectStart = (year - 1) * 100000;
            var projectEnd = (year + 1) * 100000;
            var divider = 15000;

            ExtractData(year, 0, projectStart, currentAction);

            for (int i = 0; i < ((projectEnd - projectStart) / divider); i++)
                ExtractData(year, projectStart + divider * i + 1, projectStart + divider * (i + 1), currentAction);

            ExtractData(year, projectEnd + 1, 999999999999, currentAction);
            currentAction.Description = string.Format("Application Extraction {0}: Copy has finished", year);
        }

        private static void ExtractData(int year, long projectStart, long projectEnd, ICurrentAction action)
        {
            var query = ApplicationBookOfWork.GetEntrepotQueryString(year, projectStart, projectEnd);

            action.Description = query;

            SqlHelper.CopyDataFromAnotherDatabase(EntrepotConnectionString, query, string.Format("ApplicationBookOfWork{0}", year),
                    PtsConnectionString, ApplicationBookOfWork.ColumnMappings);
        }
    }

    public class ApplicationExtractionCurrentYear : CurrentYear
    {
        static string PtsConnectionString { get { return ConfigurationManager.AppSettings["PtsConnectionString"]; } }

        protected override void ExecuteProcess(DateTime referenceDate, ref ICurrentAction currentAction, string networkUser, string networkPassword, Dictionary<string, object> parameters)
        {
            if (referenceDate.Month == 12 || referenceDate.Month == 1)
            {
                var year = referenceDate.Month == 12 ? referenceDate.Year + 2 : referenceDate.Year + 1;

                currentAction.Description = string.Format("Checking if ApplicationBookOfWork{0} exists. If it doesn't exist it will be created.", year);
                var queryCreateTableNewYear = ApplicationBookOfWork.GetQueryCreateTableNewYear(year, false);
                SqlHelper.ExecuteReader(queryCreateTableNewYear, PtsConnectionString);
            }

            ApplicationExtraction.ExtractData(referenceDate.Year, ref currentAction, parameters, referenceDate);
        }
    }

    public class ApplicationExtractionNextYear : NextYear
    {
        protected override void ExecuteProcess(DateTime referenceDate, ref ICurrentAction currentAction, string networkUser, string networkPassword, Dictionary<string, object> parameters)
        {
            ApplicationExtraction.ExtractData(referenceDate.Year + 1, ref currentAction, parameters, referenceDate);
        }
    }

    public class ApplicationExtractionPreviousYear : PreviousYear
    {
        protected override void ExecuteProcess(DateTime referenceDate, ref ICurrentAction currentAction, string networkUser, string networkPassword, Dictionary<string, object> parameters)
        {
            ApplicationExtraction.ExtractData(referenceDate.Year - 1, ref currentAction, parameters, referenceDate);
        }
    }
}
